<?php

/**
 * Resource file for US style mailing addresses
 *
 * PHP version 5
 *
 * LICENSE:
 *
 * Copyright (c) 2008-2009, Philippe Jausions / 11abacus
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of 11abacus nor the names of its contributors may
 *     be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category  Structures
 * @package   Structures_Location
 * @author    Philippe Jausions <Philippe.Jausions@11abacus.com>
 * @copyright 2008-2009 by Philippe Jausions / 11abacus
 * @license   http://www.opensource.net/licenses/bsd-license.php New BSD
 */

/**
 * Required dependencies
 */
require_once 'Structures/Location/PostalResourceInterface.php';

/**
 * Resource file for US style mailing addresses
 *
 * @category Structures
 * @package  Structures_Location
 * @author   Philippe Jausions <Philippe.Jausions@11abacus.com>
 */
class Structures_Location_US_Resource
implements Structures_Location_PostalResourceInterface
{
    /**
     * Regions types
     */
    const REGION_TYPE_CONTIGUOUS = 'Contiguous';
    const REGION_TYPE_STATES = 'States';
    const REGION_TYPE_POSSESSIONS = 'Possessions';
    const REGION_TYPE_MILITARY = 'Military';

    /**
     * List of states and their code 
     * 
     * (The District of Columbia is considered a state for this list)
     *
     * @var array code => English name
     */
    static protected $states = array(
        'AL' => 'Alabama',
        'AK' => 'Alaska',
        'AZ' => 'Arizona',
        'AR' => 'Arkansas',
        'CA' => 'California',
        'CO' => 'Colorado',
        'CT' => 'Connecticut',
        'DE' => 'Delaware',
        'DC' => 'District of Columbia',
        'FL' => 'Florida',
        'GA' => 'Georgia',
        'HI' => 'Hawaii',
        'ID' => 'Idaho',
        'IL' => 'Illinois',
        'IN' => 'Indiana',
        'IA' => 'Iowa',
        'KS' => 'Kansas',
        'KY' => 'Kentucky',
        'LA' => 'Louisiana',
        'ME' => 'Maine',
        'MD' => 'Maryland',
        'MA' => 'Massachusetts',
        'MI' => 'Michigan',
        'MN' => 'Minnesota',
        'MS' => 'Mississippi',
        'MO' => 'Missouri',
        'MT' => 'Montana',
        'NE' => 'Nebraska',
        'NV' => 'Nevada',
        'NH' => 'New Hampshire',
        'NJ' => 'New Jersey',
        'NM' => 'New Mexico',
        'NY' => 'New York',
        'NC' => 'North Carolina',
        'ND' => 'North Dakota',
        'OH' => 'Ohio',
        'OK' => 'Oklahoma',
        'OR' => 'Oregon',
        'PA' => 'Pennsylvania',
        'RI' => 'Rhode Island',
        'SC' => 'South Carolina',
        'SD' => 'South Dakota',
        'TN' => 'Tennessee',
        'TX' => 'Texas',
        'UT' => 'Utah',
        'VT' => 'Vermont',
        'VA' => 'Virginia',
        'WA' => 'Washington',
        'WV' => 'West Virginia',
        'WI' => 'Wisconsin',
        'WY' => 'Wyoming',
    );

    /**
     * List of US possessions and their code
     *
     * @var array code => English name
     */
    static protected $possessions = array(
        'AS' => 'American Samoa',
        'FM' => 'Federated States of Micronesia',
        'GU' => 'Guam',
        'MH' => 'Marshall Islands',
        'MP' => 'Northern Mariana Islands',
        'PW' => 'Palau',
        'PR' => 'Puerto Rico',
        'VI' => 'Virgin Islands',
    );

    /**
     * List of military "states" and their code
     *
     * @var array code => English name
     */
    static protected $military = array(
        'AE' => 'Armed Forces Europe, Canada, Africa & Middle East',
        'AA' => 'Armed Forces Americas (except Canada)',
        'AP' => 'Armed Forces Pacific',
    );

    /**
     * List of secondary with their abbreviation and secondary spellings
     *
     * @var array Abbreviation => list of often used equivalent (and typos?)
     */
    static protected $units = array(
        'Apt.'  => array('Apartment', 'Apmt.'),
        'Bsmt.' => array('Basement'),
        'Bldg.' => array('Building', 'Bld.'),
        'Dept.' => array('Department', 'Dpt.'),
        'Fl.'   => array('Floor', 'Flr.'),
        'Frnt.' => array('Front', 'Frt.'),
        'Hngr.' => array('Hangar'),
        'Lbby.' => array('Lobby', 'Lby.'),
        'Lot'   => array('Lot', 'Lt.'),
        'Lowr.' => array('Lower', 'Lwr.'),
        'Ofc.'  => array('Office', 'Off.', 'Offc.'),
        'Ph.'   => array('Penthouse', 'Pent.', 'Pnth.'),
        'Pier'  => array('Pier'),
        'Rear'  => array('Rear'),
        'Rm.'   => array('Room'),
        'Side'  => array('Side'),
        'Slip'  => array('Slip', 'Slp.'),
        'Spc.'  => array('Space'),
        'Stop'  => array('Stop', 'Stp.'),
        'Ste.'  => array('Suite'),
        'Trlr.' => array('Trailer', 'Trl.'),
        'Unit'  => array('Unit'),
        'Uppr.' => array('Upper', 'Upr.', 'Up.'),
    );

    /**
     * Returns list of state/possesion/Military codes and names
     * 
     * (The District of Columbia is considered a state for this list)
     *
     * @param string $type Region type to narrow the list to
     *
     * @return array Uppercase 2-letter state/possession/military code => name
     * @see    getRegionTypes
     */
    public function getRegions($type = null)
    {
        if ($type === null) {
            return array_merge($this->getStates(), $this->getPossessions(),
                               $this->getMilitaryCodes());
        }
        switch ($type) {
        case self::REGION_TYPE_CONTIGUOUS:
            $regions = $this->getStates();
            unset($regions['HI']);
            unset($regions['AK']);
            return $regions;
            break;
        case self::REGION_TYPE_STATES:
            return $this->getStates();
            break;
        case self::REGION_TYPE_MILITARY:
            return $this->getMilitaryCodes();
            break;
        case self::REGION_TYPE_POSSESSIONS:
            return $this->getPossessions();
            break;
        }
        throw new Structures_Location_Exception_Invalid('Invalid region type: '
                                                        .$type);
    }

    /**
     * Returns list of state codes and names
     *
     * @return array Uppercase 2-letter state code => name
     */
    public function getStates()
    {
        return self::$states;
    }

    /**
     * Returns list of US possesion codes and names
     *
     * @return array Uppercase 2-letter US possession code => name
     */
    public function getPossessions()
    {
        return self::$possessions;
    }

    /**
     * Returns list of military "state" codes and names
     *
     * @return array Uppercase 2-letter military "state" code => name
     */
    public function getMilitaryCodes()
    {
        return self::$military;
    }

    /**
     * Returns a list of secondary units
     *
     * @return array Abbreviation => array[Full word, alternatives...]
     */
    public function getSecondaryUnits()
    {
        return self::$units;
    }

    /**
     * Returns a list of country code for which USPS directly deliver mails for.
     *
     * @return array List of 2 upper case letter country codes (ISO-3166-2)
     */
    public function getDeliveryCountryCodes()
    {
        return array('US', 'PR', 'MH', 'VI', 'AS', 'FM', 'GU', 'MP', 'PW');
    }

    /**
     * Returns the list of countries that is in charge of delivering the mail
     * in the United States
     *
     * @return array 2 upper case letter country codes (ISO-3166-2)
     */
    public function getDelivererCountryCodes()
    {
        return array('US');
    }

    /**
     * Returns list of codes and names
     * 
     * @param string $regionCode NULL or region code
     * @param string $type       Sub-region type to narrow the list to
     *
     * @return array Uppercase 2-char "département" code => name
     * @see    getSubRegionTypes()
     */
    public function getSubRegions($region = null, $type = null)
    {
        return array();
    }

    /**
     * Returns a list of region types available
     * 
     * The types returned can be used with getRegions() method
     *
     * @return array Region type => English name
     * @see    getRegions()
     */
    public function getRegionTypes()
    {
        return array(
            self::REGION_TYPE_CONTIGUOUS => 'Contiguous US',
            self::REGION_TYPE_MILITARY => 'Military',
            self::REGION_TYPE_POSSESSIONS => 'Possessions',
            self::REGION_TYPE_STATES => 'All States & DC',
        );
    }

    /**
     * Returns a list of sub-region types available
     * 
     * The types returned can be used with getSubRegions() method
     *
     * @return array Sub-region type => name
     * @see    getSubRegions()
     */
    public function getSubRegionTypes()
    {
        return array();
    }
}

?>